/**
 * applyMiddleware 应用中间件的方法，可以接受一个，也可以接受多个中间件
 * 用法：applyMiddleware(中间件名称，中间件名称)
 * compose store增强, 意思就是往我们的store中增加新的方法
 * compose(方法名，方法名，也可以是一个纯函数)
 * createStore 用于创建一个store库
 */
import { createStore, applyMiddleware, compose } from "redux";

// 中间件，一个用于redux的promise插件, 修改了store.dispatch方法，使它能接受一个promise做为参数
import promise from "redux-promise";
// 中间件，仍然是用于处理异步的插件，修改了store.dispatch方法，使它能接受一个函数作为参数
import thunk from "redux-thunk";

// 引入reducer, 这个reducer是由多个reduce组成的对象
// 它需要的是一个export{reduce1, reduce2}这种格式
// 由combineReducers合并抛出
import reducer from "./index";

// 导入axios的封装 让我们的组件在使用thunk读取异步数据时
//可以直接使用post 或 get
import { post, get } from "@/Utils/http";

// 数据持久化
// persistReducer 持久化我们的reducer, persistStore 持久化我们的store
import { persistReducer, persistStore } from "redux-persist";

// 自动合并持久化数据（深度合并）
import autoMergeLevel2 from "redux-persist/lib/stateReconciler/autoMergeLevel2";
// 使用LocalStorage来存储我们的数据
import storage from "redux-persist/lib/storage";
// 使用sessionStorage来存储我们的数据
import storageSession from "redux-persist/lib/storage/session";

// 数据持久化的配置项
const rootPersistConfig = {
  key: "root", // 用于在storege中存储信息
  storage: storage, // 存储的方法
  // 深度合并
  stateReconciler: autoMergeLevel2,
  // 白名单
  // whitelist: ["reduxExercise", "loginAction", "mockList"], // 字符串格式(export default reduce 函数的名称)
  // blacklist: [],
};
// 加入redux浏览器调试工具
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

//
// const reducerMiddleware = applyMiddleware(promise, thunk)

// 创建一个story
export const store = createStore(
  // 使用persist管理我们所有的reducer
  // 持久化我们的reduce,它接受两个参数，第一个参数是我们在上面配置的配置项
  // 第二个是我们通过reducer.index.js export的reduce对象，如果是只有一个reduce的话，可以不用combineReducers
  persistReducer(rootPersistConfig, reducer),
  // combineReducers(Reducer),
  // 中间件的引入(composeEnhancers, 加入浏览器调试工具的compose, 可以认为它就是compose)
  // composeEnhancers(applyMiddleware(promise, thunk))
  // reducer,
  composeEnhancers(
    applyMiddleware(promise, thunk.withExtraArgument({ get, post }))
  )
);

// 需要把配置好的persistor抛出 方便在index中使用
export const persistor = persistStore(store);

export default store;

// // 所以 Redux-Thunk 其实就是把 Store 中的 dispatch 方法重写了
// // 如果 dispatch 的参数是正常的 Action，也就是说是个对象，那就直接 dispatch 它。
// // 如果参数是一个方法，那就传入 dispatch 和 getState 并执行它
// // 而 dispatch 和 getState 是在 createStore 时以闭包的方式注入的。

// // 外面包了一层函数createThunkMiddleware接受额外的参数
// function createThunkMiddleware(extraArgument){

//   // 从store中解析出dispatch，getState
//   return ({dispatch,getState}) => {
//     next =>
//     action => {

//       // 判断action类型 是否为函数类型 如果是函数
//       // 执行这个action并传入 dispatch 和 getState 及 extraArgument 为参数
//       if(typeof action === 'function'){
//         return action(dispatch,getState , extraArgument)
//       }
//       // 直接dispatch
//        // next 为 store.dispatch
//       return next(action)
//     }
//   }
// }

// // thunk中间件其实相当于没传extraArgument：
// const thunk = createThunkMiddleware()

// // 将createThunkMiddleware 直接暴露给withExtraArgument
// thunk.withExtraArgument = createThunkMiddleware
// export default thunk

// import isPromise from 'is-promise';
// import { isFSA } from 'flux-standard-action';

// export default function promiseMiddleware({ dispatch }) {
//     return next => action => {

//       // 判断是不是标准的FSA
//         if (!isFSA(action)) {
//           // 判断是不是promise 如果是则执行
//           // 只会处理resolve的值
//           // 反之交给下一个中间件
//             return isPromise(action) ? action.then(dispatch) : next(action);
//         }

//         // 是标准的FSA, 判断是不是一个promise
//         return isPromise(action.payload)
//         // 如果是promise的时候，执行then,同时捕获异常，
//         // 在处理这两种情况以后，会分别添加另外一个约束error
//         // 这我们需要在reducer里面还需要判断error的值，做不同的处理

//             ? action.payload
//                 .then(result => dispatch({ ...action, payload: result }))
//                 .catch(error => {
//                     dispatch({ ...action, payload: error, error: true });
//                     return Promise.reject(error);
//                 })
//           //  如果不是promise则交给下一个中间件
//             : next(action);
//     };
// }
